package jfae.core.properties;

import javax.persistence.Temporal;

import jfae.core.properties.parsers.PropertyHandler;



/**
 * Root interface for entity property representation
 * Given the above class definition
 * <div class="codeblock">
 * <pre>
 * public class BaseEntity {
 * 
 * 	private String stringProp;
 * 	private Integer integerProp;
 * 	private Long longProp;
 * 	private Date dateProp;
 * 	private Boolean booleanProp;
 * 	
 * 	&#64;Editable(order=1)
 * 	public String getStringProp() {
 * 		return stringProp;
 * 	}
 * 	public void setStringProp(String stringProp) {
 * 		this.stringProp = stringProp;
 * 	}
 * 	&#64;Editable(order=2)
 * 	public Integer getIntegerProp() {
 * 		return integerProp;
 * 	}
 * 	public void setIntegerProp(Integer integerProp) {
 * 		this.integerProp = integerProp;
 * 	}
 * 	&#64;Editable(order=3)
 * 	public Long getLongProp() {
 * 		return longProp;
 * 	}
 * 	public void setLongProp(Long longProp) {
 * 		this.longProp = longProp;
 * 	}
 * 	&#64;Editable(order=4)
 * 	public Date getDateProp() {
 * 		return dateProp;
 * 	}
 * 	public void setDateProp(Date dateProp) {
 * 		this.dateProp = dateProp;
 * 	}
 * 	&#64;Editable(order=5)
 * 	public Boolean getBooleanProp() {
 * 		return booleanProp;
 * 	}
 * 	public void setBooleanProp(Boolean booleanProp) {
 * 		this.booleanProp = booleanProp;
 * 	}
 * 	
 * }
 * </pre>
 * </div>
 * this interface allow you mapping every relevant information on certains property.
 * Mapping of Entity property (where entity A contains a property of type entity B) is not covered by this interface. 
 * @author bobpuley
 *
 * @param <T>
 */
public interface FieldInfo<T> {
	
	/**
	 * The name of the property mapped.
	 * Given the above class definition
	 * <code>
	 * <pre>
	 * class Entity{
	 * 	&#64;Editable(order=1)
	 * 	public String getStringProp() {
	 * 		return this.stringProp;
	 * 	}
	 * }
	 * </pre>
	 * </code>
	 * name is <em>stringProp</em>
	 * @return the name of the property
	 */
	public String getName();
	
	/**
	 * The name of the property mapped.
	 * Given the above class definition
	 * <code>
	 * <pre>
	 * class Entity{
	 * 	&#64;Editable(order=1)
	 * 	public String getStringProp() {
	 * 		return this.stringProp;
	 * 	}
	 * }
	 * </pre>
	 * </code>
	 * type is <em>java.lang.String</em>
	 * @return the name of the property
	 */
	public Class<T> getType();

	/**
	 * The name of the property mapped.
	 * Given the above class definition
	 * <code>
	 * <pre>
	 * class Entity{
	 * 	&#64;Editable
	 * 	public String getStringProp() {
	 * 		return this.stringProp;
	 * 	}
	 * }
	 * </pre>
	 * </code>
	 * order is {@link Integer#MAX_VALUE} if <code>&#64;Editable(order=)</code> is not set,
	 * otherwise the annotation order value is used.
	 * @return the name of the property
	 */
	public int getOrder();

	// TODO: valutare se spostare questo metodo in una classe di utilità
	public boolean isEnum();

	// TODO: valutare se spostare questo metodo in una classe di utilità
	public boolean isEntity();

	// TODO: valutare se spostare questo metodo in una classe di utilità
	public boolean isInGroup(String group);
	
	/**
	 * Validation information, if true the property is mandatory in order to
	 * save/update enclosing entity. 
	 * Automatic discovery depends on based orm. For example in JPA you can
	 * use {@link NotNull} annotation. The specific {@link PropertyHandler}
	 * is responsible to implement needed logic to parse correctly information.
	 * @return true if property is mandatory, else false.
	 */
	public boolean isRequired();

	/**
	 * Presentation info about label for this property.
	 * Useful for labeling form input or table column header
	 * @return the configured label for mapped property
	 */
	public String getLabel();

	/**
	 * In case of currency, floating values and double values,
	 * you can specify the format string to be used for property 
	 * value formatting in rendering phase
	 * @return the formatting string /pattern or null/empty string
	 */
	public String getFormat();

	/**
	 * Indicate if the property is a date/date-time or time only.
	 * Automatic discovery depends on based orm. For example in JPA you can
	 * use {@link Temporal} annotation. The specific {@link PropertyHandler}
	 * is responsible to implement needed logic to parse information correctly.
	 * @return true if the property is time only
	 */
	public boolean isTime();
	
	/**
	 * TODO: valutare se renderlo campo String semplice. La domanda è: ha senso mappare una proprietà su gruppi diversi?
	 * Array of groups names, useful for form layout purposes
	 * @return the groups names
	 */
	public String[] getGroups();
	
	/**
	 * Indicate the width of the field on presentation tier
	 * @return integer positive number if is set, otherwise -1 
	 */
	public int getFieldSize();
	
	/**
	 * TODO: valutare se sia utile o meno
	 * Indicate the width of the column of a table on presentation tier
	 * @return integer positive number if is set, otherwise -1 
	 */
	public int getColumnSize();
	

	/**
	 * Provide a list of comma separated styles to applied to view
	 * @return a list of comma separated styles or emtpy string
	 */
	public String getStyles();
	
	/**
	 * Provide a list of space separated css class
	 * @return a list of space separated css class or emtpy string
	 */
	public String getStyleClass();
	
	/**
	 * Indicate the max number of chars allowed
	 * @return a integer positive number if is set, otherwise -1
	 */
	public int getFieldLength();

	/**
	 * TODO: probabilmente da spostare in un wrapper della vista
	 * @return the component id
	 */
	public String getIdentifier();
	
	/**
	 * TODO: da valutare indicherebbe una proprietà annidata
	 * @return
	 */
	public String getPropertyName();
	
	/**
	 * TODO: come {@link #getPropertyName()} è legato alle proprietà annidate
	 * @return
	 */
	public String getExpression();
	
	public void setLabel(String label);
	
	public void setName(String name);
	
	public void setType(Class<T> type);
	
	public void setOrder(int order);
	
	public void setRequired(boolean required);
	
	public void setFormat(String format);
	
	public void setTime(boolean time);
	
	public void setGroups(String[] groups);
	
	public void setStyles(String styles);
	
	public void setStyleClass(String styleClass);
	
	public void setColumnSize(int columnSize);
	
	public void setFieldSize(int fieldSize);
	
	public void setFieldLength(int fieldLength);

	public void setPosition(int position);
	
	public FieldInfo<T> clone();
}
